home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / Tickle-4.0 (tcl) / tcl / src / stat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  8.6 KB  |  441 lines  |  [TEXT/MPS ]

  1.  
  2. #ifdef MPW
  3. #    pragma segment TCL_2
  4. #endif
  5.  
  6. /*********************************************************************
  7. File        :    stat.c            -    Macintosh implementation of stat()
  8. Author    :    Matthias Neeracher
  9. Started    :    28May91                                Language    :    MPW C
  10.                 28May91    MN    Created
  11.                 28May91    MN    isatty()
  12. Last        :    28May91
  13.  
  14. Copyright (c) 1991, Matthias Neeracher
  15. Copyright (c) 1993, Tim Endres - modifications
  16.  
  17. Permission is granted to anyone to use this software for any
  18. purpose on any computer system, and to redistribute it freely,
  19. subject to the following restrictions:
  20.  
  21. 1. The author is not responsible for the consequences of use of
  22.     this software, no matter how awful, even if they arise
  23.     from defects in it.
  24.  
  25. 2. The origin of this software must not be misrepresented, either
  26.     by explicit claim or by omission.
  27.  
  28. 3. Altered versions must be plainly marked as such, and must not
  29.     be misrepresented as being the original software.
  30.  
  31. *********************************************************************/
  32.  
  33. #include <string.h>
  34. #include "ioctl.h"
  35. #include <errno.h>
  36. #include <Errors.h>
  37. #include <Files.h>
  38.  
  39. #include "tcl.h"
  40. #include "tclUnix.h"
  41.  
  42. /* As the field names of a CInfoParamBlockRec are spelled inconsistently,
  43.     we have to use manual casts.
  44. */
  45.  
  46. #define FILEINFO(cb)    (*(HFileInfo *) (cb))
  47. #define DIRINFO(cb)    (*(DirInfo *) (cb))
  48.  
  49. OSErr
  50. GetCatInfo(char * path, CInfoPBPtr cb)
  51.     {
  52.     char    *    nextPath;
  53.     char    *  tryPath;
  54.     OSErr        err;
  55.     Str255    name;
  56.  
  57.     DIRINFO(cb).ioNamePtr    =    name;
  58.     DIRINFO(cb).ioDrDirID    =    0;
  59.     DIRINFO(cb).ioVRefNum    =    0;
  60.     DIRINFO(cb).ioFDirIndex    =    0;
  61.  
  62.     /* handle very long pathnames */
  63.  
  64.     while (strlen(path) > 255)
  65.         {
  66.         for (nextPath    =    path; tryPath = strchr(nextPath, ':'); nextPath = tryPath)
  67.             if (tryPath-nextPath > 31)
  68.                 return bdNamErr;
  69.             else if (tryPath-path > 255)
  70.                 break;
  71.  
  72.         if (nextPath == path && !tryPath)
  73.             return bdNamErr;
  74.  
  75.         name[0]    =    nextPath-path;
  76.         strncpy((char *) name+1, path, name[0]);
  77.  
  78.         err = PBGetCatInfo(cb, false);
  79.         if (err != noErr)
  80.             return err;
  81.  
  82.         if (! (DIRINFO(cb).ioFlAttrib & 0x10))
  83.             {
  84.             return bdNamErr;
  85.             }
  86.  
  87.         DIRINFO(cb).ioFDirIndex    =    0;
  88.  
  89.         path    =    nextPath+1;
  90.         }
  91.     
  92.     name[0]    =    strlen(path);
  93.     strncpy((char *) name+1, path, name[0]);
  94.  
  95.     err = PBGetCatInfo(cb, false);
  96.     
  97.     return err;
  98.     }
  99.  
  100. OSErr    GetFDCatInfo(int fd, CInfoPBPtr cb)
  101.     {
  102.     short                fRef;
  103.     OSErr                err;
  104.     FCBPBRec            fcb;
  105.     Str255            fname;
  106.  
  107.     if (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1)
  108.         return fnfErr;
  109.  
  110.     fcb.ioNamePtr    =     fname;
  111.     fcb.ioRefNum    =    fRef;
  112.     fcb.ioFCBIndx    =     0;
  113.     err = PBGetFCBInfo(&fcb, false);
  114.     if (err != noErr)
  115.         return err;
  116.  
  117.     FILEINFO(cb).ioNamePtr        =    fname;
  118.     FILEINFO(cb).ioDirID        =    fcb.ioFCBParID;
  119.     FILEINFO(cb).ioVRefNum        =    fcb.ioFCBVRefNum;
  120.     FILEINFO(cb).ioFDirIndex    =    0;
  121.  
  122.     return PBGetCatInfo(cb, false);
  123.     }
  124.  
  125. OSErr GetVolume(char * path, ParmBlkPtr pb)
  126.     {
  127.     char *    volEnd;
  128.     OSErr        err;
  129.     WDPBRec    wd;
  130.     Str255    name;
  131.  
  132.     volEnd    =    strchr(path, ':');
  133.  
  134.     pb->volumeParam.ioNamePtr    =    name;
  135.  
  136.     if (path[0] == ':' || ! volEnd)
  137.         {
  138.         err = PBGetVol(pb, false);
  139.         if (err != noErr)
  140.             return err;
  141.         
  142.         wd.ioNamePtr    =    name;
  143.         wd.ioVRefNum    =     pb->volumeParam.ioVRefNum;
  144.         wd.ioWDIndex    =    0;
  145.         err = PBGetWDInfo(&wd, false);
  146.         if (err == noErr)
  147.             pb->volumeParam.ioVRefNum    =    wd.ioWDVRefNum;
  148.             
  149.         pb->volumeParam.ioVolIndex    =    0;
  150.         }
  151.     else
  152.         {
  153.         pb->volumeParam.ioVolIndex    =    -1;
  154.  
  155.         name[0]    =    (volEnd - path) + 1; /* include ':' */
  156.         strncpy((char *) name+1, path, name[0]);
  157.         }
  158.  
  159.     err = PBGetVInfo(pb, false);
  160.     
  161.     return err;
  162.     }
  163.  
  164. OSErr
  165. GetFDVolume(int fd, ParmBlkPtr pb)
  166.     {
  167.     OSErr                err;
  168.     short                fRef;
  169.     Str255            name;
  170.     FCBPBRec            fcb;
  171.  
  172.     if ( ioctl(fd, FIOREFNUM, (long *) &fRef) == -1 )
  173.         return fnfErr;
  174.  
  175.     fcb.ioNamePtr    =     name;
  176.     fcb.ioRefNum    =    fRef;
  177.     fcb.ioFCBIndx    =     0;
  178.     if (err = PBGetFCBInfo(&fcb, false))
  179.         return err;
  180.  
  181.     pb->volumeParam.ioNamePtr    =    name;
  182.     pb->volumeParam.ioVRefNum    =    fcb.ioFCBVRefNum;
  183.     pb->volumeParam.ioVolIndex    =    0;
  184.  
  185.     return PBGetVInfo(pb, false);
  186.     }
  187.  
  188. int    
  189. mac_do_stat(CInfoPBPtr cb, ParmBlkPtr pb, struct stat * buf)
  190.     {
  191.     buf->st_ino        =    FILEINFO(cb).ioDirID;
  192.     buf->st_dev        =    pb->ioParam.ioVRefNum;
  193.     buf->st_nlink    =    1;
  194.     buf->st_uid        =    0;
  195.     buf->st_gid        =    0;
  196.     buf->st_atime    =    FILEINFO(cb).ioFlMdDat;
  197.     buf->st_mtime    =    FILEINFO(cb).ioFlMdDat;
  198.     buf->st_ctime    =    FILEINFO(cb).ioFlCrDat;
  199.     buf->st_blksize=    pb->volumeParam.ioVAlBlkSiz;
  200.  
  201.     if (FILEINFO(cb).ioFlAttrib & 0x10)
  202.         {
  203.         /* DIRECTORY */
  204.         buf->st_mode    =    S_IFDIR | 0777;
  205.         buf->st_size    =    buf->st_blksize;    /* Not known for directories    */
  206.         buf->st_rdev    = 0;                        /* UNDONE - couldn't this be a "wdRefnum" if one exists? */
  207.         buf->st_nlink  = DIRINFO(cb).ioDrNmFls;
  208.  
  209.         buf->st_rsize = 0;
  210.         buf->st_parid = DIRINFO(cb).ioDrParID;
  211.  
  212.         buf->fdType        = (long)'Fldr';
  213.         buf->fdCreator    = (long)'Fldr';
  214. /* UNDONE - another time maybe...
  215.         buf->finfo        = FILEINFO(cb).ioFlFndrInfo;
  216.         buf->fxinfo        = FILEINFO(cb).ioFlXFndrInfo;
  217.  */
  218.         }
  219.     else
  220.         {
  221.         /* FILE */
  222.         buf->st_mode    =    S_IFREG | 0666;
  223.         buf->st_size = FILEINFO(cb).ioFlLgLen;
  224.         buf->st_rdev = FILEINFO(cb).ioFRefNum;
  225.  
  226.         if (FILEINFO(cb).ioFlAttrib & 0x01)        /* not locked? */
  227.             buf->st_mode &= 0222;
  228.         
  229.         if (FILEINFO(cb).ioFlFndrInfo.fdType == 'APPL')
  230.             buf->st_mode |= 0111;
  231.         
  232.         buf->st_rsize = FILEINFO(cb).ioFlRLgLen;
  233.         buf->st_parid = FILEINFO(cb).ioFlParID;
  234.  
  235.         buf->fdType        = FILEINFO(cb).ioFlFndrInfo.fdType;
  236.         buf->fdCreator    = FILEINFO(cb).ioFlFndrInfo.fdCreator;
  237. /* UNDONE - another time maybe...
  238.         buf->finfo        = FILEINFO(cb).ioFlFndrInfo;
  239.         buf->fxinfo        = FILEINFO(cb).ioFlXFndrInfo;
  240.  */
  241.         }
  242.  
  243.     buf->st_blocks    =    (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
  244.  
  245.     return 0;
  246.     }
  247.  
  248. int
  249. stat(char * path, struct stat * buf)
  250.     {
  251.     int                result;
  252.     CInfoPBRec        cb;
  253.     ParamBlockRec    pb;
  254.  
  255.     if (GetCatInfo(path, &cb) || GetVolume(path, &pb))
  256.         {
  257.         errno = ENOENT;
  258.         return -1;
  259.         }
  260.     else
  261.         {
  262.         result = mac_do_stat(&cb, &pb, buf);
  263.         return result;
  264.         }
  265.     }
  266.  
  267. int
  268. lstat(char * path, struct stat * buf)
  269.     {
  270.     return stat(path, buf);
  271.     }
  272.  
  273. int
  274. fstat(int fd, struct stat * buf)
  275.     {
  276.     int                result;
  277.     CInfoPBRec        cb;
  278.     ParamBlockRec    pb;
  279.  
  280.     if (GetFDCatInfo(fd, &cb) || GetFDVolume(fd, &pb))
  281.         {
  282.         errno = ENOENT;
  283.  
  284.         return -1;
  285.         }
  286.     else
  287.         {
  288.         result = mac_do_stat(&cb, &pb, buf);
  289.         if ( ! ioctl(fd, FIOINTERACTIVE, NULL) )
  290.             {
  291.             /* MPW window */
  292.             buf->st_mode        |=    S_IFCHR;
  293.             buf->st_atime        =    time(NULL);
  294.             buf->st_mtime        =    time(NULL);
  295.             buf->st_ctime        =    time(NULL);
  296.             }
  297.         return result;
  298.         }
  299.     }
  300.  
  301. int
  302. access(const char *filename, int mode)
  303.     {
  304.     struct stat        statbuf;
  305.  
  306.     if ( stat((char *)filename, &statbuf) < 0 )
  307.         {
  308.         return -1;
  309.         }
  310.     
  311.     if ( S_ISDIR( statbuf.st_mode ) )
  312.         {
  313.         /* DIR */        /* R_OK, W_OK, X_OK, F_OK */
  314.         if ( (mode & W_OK) != 0 )
  315.             return -1;
  316.         
  317.         return 0;
  318.         }
  319.     else
  320.         {
  321.         /* FILE */
  322.         if ( (mode & W_OK) != 0 )    /* UNDONE - use MacOS call for better results! */
  323.             if (statbuf.st_rdev > 0)    /* it is open... */
  324.                 return -1;
  325.         
  326.         if ( (mode & X_OK) != 0 )    /* UNDONE - use MacOS call for better results! */
  327.             if (statbuf.fdType != (long)'APPL')
  328.                 return -1;
  329.         
  330.         return 0;
  331.         }
  332.  
  333.     return 0;
  334.     }
  335.  
  336. #ifndef THINK_C
  337.  
  338. int
  339. isatty(int fd)
  340.     {
  341.     return !ioctl(fd, FIOINTERACTIVE, NULL);
  342.     }
  343.     
  344. #endif
  345.  
  346. #ifdef test
  347.  
  348. #include <stdio.h>
  349.  
  350. #define DUMP(EXPR, MODE)    printf("%s = %"#MODE"\n", #EXPR, EXPR);
  351.  
  352. int main(int argc, char ** argv)
  353. {
  354.     int             res;
  355.     struct stat    statbuf;
  356.  
  357.     printf("StdIn is %s TTY.\n", isatty(0)?"a":"no");
  358.     printf("StdOut is %s TTY.\n", isatty(1)?"a":"no");
  359.     printf("StdErr is %s TTY.\n\n", isatty(2)?"a":"no");
  360.     
  361.     if (argc == 1)
  362.         res = fstat(0, &statbuf);
  363.     else
  364.         res = stat(argv[1], &statbuf);
  365.  
  366.     if (res)
  367.         printf("Error occurred.\n");
  368.     else {
  369.         DUMP(statbuf.st_dev,d);
  370.         DUMP(statbuf.st_ino,d);
  371.         DUMP(statbuf.st_mode,#o);
  372.         DUMP(statbuf.st_nlink,d);
  373.         DUMP(statbuf.st_uid,d);
  374.         DUMP(statbuf.st_gid,d);
  375.         DUMP(statbuf.st_rdev,d);
  376.         DUMP(statbuf.st_size,d);
  377.         DUMP(statbuf.st_atime,u);
  378.         DUMP(statbuf.st_mtime,u);
  379.         DUMP(statbuf.st_ctime,u);
  380.         DUMP(statbuf.st_blksize,d);
  381.         DUMP(statbuf.st_blocks,d);
  382.     }
  383. return 0;
  384. }
  385. #endif
  386.  
  387. #ifdef NEVER_DEFINED
  388.  
  389. cd {tclSrc}
  390. C -mbg full -d test {active}
  391. Link -t "MPST" -c "MPS "        ∂
  392.     -o teststat                        ∂
  393.     {active}.o                        ∂
  394.     {Libraries}RunTime.o            ∂
  395.     {Libraries}Interface.o        ∂
  396.     {CLibraries}StdCLib.o
  397. teststat ""
  398. StdIn is a TTY.
  399. StdOut is a TTY.
  400. StdErr is a TTY.
  401.  
  402. statbuf.st_dev = -2
  403. statbuf.st_ino = 131324
  404. statbuf.st_mode = 040777
  405. statbuf.st_nlink = 45
  406. statbuf.st_uid = 0
  407. statbuf.st_gid = 0
  408. statbuf.st_rdev = 0
  409. statbuf.st_size = 3584
  410. statbuf.st_atime = 2834961968
  411. statbuf.st_mtime = 2834961968
  412. statbuf.st_ctime = 2834354745
  413. statbuf.st_blksize = 3584
  414. statbuf.st_blocks = 1
  415.  
  416. pwd
  417. Moon:tcl7.0:
  418.  
  419. teststat Moon:tcl7.0:src
  420. StdIn is a TTY.
  421. StdOut is a TTY.
  422. StdErr is a TTY.
  423.  
  424. statbuf.st_dev = -5
  425. statbuf.st_ino = 4648
  426. statbuf.st_mode = 040777
  427. statbuf.st_nlink = 1
  428. statbuf.st_uid = 0
  429. statbuf.st_gid = 0
  430. statbuf.st_rdev = 0
  431. statbuf.st_size = 2048
  432. statbuf.st_atime = 2834835315
  433. statbuf.st_mtime = 2834835315
  434. statbuf.st_ctime = 2834354745
  435. statbuf.st_blksize = 2048
  436. statbuf.st_blocks = 1
  437.  
  438.  
  439. #endif
  440.  
  441.